package com.citi.infocambio.siscomex.client.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;

public class InfocambioHttpClient {

	private static final transient Logger log = Logger.getLogger(InfocambioHttpClient.class);

	private HttpClient httpClient;

	public InfocambioHttpClient() throws Exception {
		httpClient = HttpClientFactory.getHttpClient();
	}
	
	public void setProxy(String proxyHost, Integer proxyPort) { 
		HttpHost proxy = new HttpHost(proxyHost, proxyPort, "http");		
		httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
	}

	private CookieStore addCookie(HttpClient httpClient, String addCookie, String domain) {

		CookieStore cookieStore = ((DefaultHttpClient) httpClient).getCookieStore();
		if (cookieStore == null) {
			cookieStore = new BasicCookieStore();
			((DefaultHttpClient) httpClient).setCookieStore(cookieStore);
		}

		log.debug("Adding cookie: " + addCookie);

		String[] addCookieTokens = addCookie.split(";");
		String cookieNameAndValue = addCookieTokens[0];
		String cookiePath = addCookieTokens[1];

		CookieVO cookieVO = parseCookie(cookieNameAndValue, cookiePath, domain);

		log.debug("Cookie: " + cookieVO + " created.");

		cookieStore.addCookie(cookieVO.getBasicClientCookie());

		return cookieStore;

	}

	private CookieVO parseCookie(String _nameAndValue, String _path, String _domain) {
		String[] cookieArr = _nameAndValue.trim().split("=");
		String[] pathArr = _path.trim().split("=");

		String name = cookieArr[0].trim();
		String value = cookieArr[1].trim();
		String path = pathArr[1].trim();

		return new CookieVO(name, value, path, _domain);

	}
	
	private String getResponseBody(HttpResponse response) throws IOException {
		InputStream is = response.getEntity().getContent();
		InputStreamReader reader = new InputStreamReader(is);
		BufferedReader buffReader = new BufferedReader(reader);

		String line;
		StringBuilder content = new StringBuilder();
		while ((line = buffReader.readLine()) != null) {
			content.append(line).append("\r\n");
		}
		return content.toString();
	}
	
	private void handleHeaders(HttpResponse response, String domain) { 
		for (Header header : response.getAllHeaders()) {
			if (header.getName().startsWith("Set-Cookie")) {
				addCookie(httpClient, header.getValue(), domain);
			}
		}
	}
	
	protected void execute(String domain, HttpRequestBase method) throws ClientProtocolException, IOException { 
		HttpResponse response = httpClient.execute(method);

		log.debug("-------------- Status Code ---------------");
		log.debug(response.getStatusLine());
		log.debug("-------------- Status Code ---------------");

		log.debug("-------------- Headers ---------------");
		//handleHeaders(response, domain);
		log.debug("-------------- Headers ---------------");

		log.debug("-------------- Body ---------------");
		String responseBody = getResponseBody(response);
		log.debug(responseBody);
		log.debug("-------------- Body ---------------");
	}

	public void get(String url, String domain) throws ClientProtocolException, IOException {
		HttpGet get = new HttpGet(url);
		execute(domain, get);
	}
	
	public void post(String url, String domain, HttpParam... params) throws ClientProtocolException, IOException { 
		HttpPost post = new HttpPost(url);
		
		List<NameValuePair> httpParams = new ArrayList<NameValuePair>();
		for (HttpParam param : params) { 
			NameValuePair pair = new BasicNameValuePair(param.getName(), param.getValue());
			httpParams.add(pair);
		}
		
		post.setEntity(new UrlEncodedFormEntity(httpParams));
		
		execute(domain, post);
	}
	

	private class CookieVO implements Serializable {

		private String name;
		private String value;
		private String path;
		private String domain;	

		public CookieVO(String name, String value, String path, String domain) {
			this.name = name;
			this.value = value;
			this.path = path;
			this.domain = domain;
		}

		public BasicClientCookie getBasicClientCookie() {
			BasicClientCookie cookie = new BasicClientCookie(name, value);
			cookie.setVersion(0);
			cookie.setDomain(domain);
			cookie.setPath(path);
			return cookie;
		}

		public String toString() {
			StringBuilder buff = new StringBuilder();
			buff.append("Cookie: {");
			buff.append("name: ").append(name);
			buff.append(", value: ").append(value);
			buff.append(", path: ").append(path);
			buff.append(", domain: ").append(domain);
			return buff.append("}").toString();
		}

	}

}
